package com.study.common.easyexcel;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * easy excel 工具类 使用
 * add by yaojinshan
 * since 20210119
 * 参看：
 *  https://github.com/alibaba/easyexcel/blob/master/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java
 */
public class EasyExcelTest {
    static final String easyExcel_01_file = "src/main/resources/template/easyExcel/easyExcel_01.xlsx";
    static final String easyExcel_02_file = "src/main/resources/template/easyExcel/easyExcel_02.xlsx";
    static Logger logger = LoggerFactory.getLogger(EasyExcelTest.class);

    public static void main(String[] args) {
//        simpleRead();
//        simpleWrite();
//        readSpecialSheet(0);
//        readSheetWithCustomConverter();
//        writeSheetWithCustomConverter();
        synchronousRead();
    }

    /**
     * 最简单的读
     * <p>1. 创建excel对应的实体对象 参照{@link EasyExcel_01}
     * <p>2. 由于默认一行行的读取excel，所以需要创建excel一行一行的回调监听器，参照{@link EasyExcel_01_Listener}
     * <p>3. 直接读即可
     */
    static void simpleRead(){
        //默认读取 第一个sheet
//        EasyExcel.read(easyExcel_01_file,EasyExcel_01.class,new EasyExcel_01_Listener()).sheet().doRead();
        //读取全部sheet 顺序读取
//        EasyExcel.read(easyExcel_01_file,EasyExcel_01.class,new EasyExcel_01_Listener()).doReadAll();
        //指定读取sheet 表头的行数，可以不指定，默认为1行；指定多行头部时，必须头部命名规范，不能是假数据
//        EasyExcel.read(easyExcel_02_file,EasyExcel_02.class,new EasyExcel_02_Listener()).sheet().headRowNumber(2).doRead();
    }
    /**
     * 最简单的写
     * <p>1. 创建excel对应的实体对象 参照{@link EasyExcel_01}
     * <p>2. 直接写即可
     */
    public static void simpleWrite() {
        String fileName = "D:/" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去读，然后写到第一个sheet，名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, EasyExcel_01.class).sheet("easyExcel简单写数据").doWrite(data());
    }

    /**
     * 读取指定的sheet数据，
     *
     */
    public static void readSpecialSheet(int sheetNum) {
        ExcelReader reader = null;
        try {
            reader = EasyExcel.read(easyExcel_01_file).build();
            //读入sheet定义 但不读取数据
            ReadSheet readSheet1 = EasyExcel.readSheet(sheetNum).head(EasyExcel_01.class).registerReadListener(new EasyExcel_01_Listener()).build();
            //读取sheet的数据
            reader.read(readSheet1);
        } finally {
            // 这里千万别忘记关闭，读的时候会创建临时文件，到时磁盘会崩的
            if (reader != null){
                reader.finish();
            }
        }
    }

    /**
     * 带类型转换器的 数据读取
     */
    public static void readSheetWithCustomConverter(){

        EasyExcel.read(easyExcel_02_file,EasyExcel_02.class,new EasyExcel_02_Listener()).sheet()
                // 这里注意 我们可以用registerConverter来指定自定义转换器， 但是这个转换变成全局了， 所有java为Integer,excel为string的都会用这个转换器。
                // 如果就想单个字段使用请使用@ExcelProperty 指定converter
//                .registerConverter(new SexConverter())
                .headRowNumber(2).doRead();
    }

    /**
     * 带类型转换的数据写操作
     * <p>1. 创建excel对应的实体对象 参照{@link EasyExcel_02}
     * <p>2. 直接写即可
     */
    public static void writeSheetWithCustomConverter() {
        String fileName = "D:/" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去读，然后写到第一个sheet，名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, EasyExcel_02.class).sheet("带类型转换的数据写操作").doWrite(data2());
    }

    /**
     * 同步读取则返回数据列表
     *      不建议使用同步读取的方式，防止数据过大，导致内存oom
     */
    public static void synchronousRead() {
        List<EasyExcel_02> dataList = EasyExcel.read(easyExcel_02_file).head(EasyExcel_02.class).sheet().headRowNumber(2).doReadSync();
        // 这里 指定读用哪个class去读，然后读取第一个sheet 同步读取会自动finish
        for (EasyExcel_02 easyExcel_02 : dataList) {
            logger.info("数据信息bean：" + easyExcel_02.toString());
        }
        // 这里 也可以不指定class，返回一个list，然后读取第一个sheet 同步读取会自动finish
        List<Map<Integer,String>> dataList2 = EasyExcel.read(easyExcel_02_file).sheet().headRowNumber(2).doReadSync();
        for (Map map : dataList2) {
            logger.info("数据信息object：" + map.toString());
        }
    }

    static List<EasyExcel_01> data(){
        List<EasyExcel_01> list = new ArrayList<>();
        list.add(new EasyExcel_01(1,"name1",new Date()));
        list.add(new EasyExcel_01(2,"name2",new Date()));
        list.add(new EasyExcel_01(3,"name3",new Date()));
        list.add(new EasyExcel_01(4,"name4",new Date()));
        list.add(new EasyExcel_01(5,"name5",new Date()));
        return list;
    }

    static List<EasyExcel_02> data2(){
        List<EasyExcel_02> list = new ArrayList<>();
        list.add(new EasyExcel_02(1,"name1",new Date(),1));
        list.add(new EasyExcel_02(2,"name2",new Date(),1));
        list.add(new EasyExcel_02(3,"name3",new Date(),0));
        list.add(new EasyExcel_02(4,"name4",new Date(),0));
        list.add(new EasyExcel_02(5,"name5",new Date(),1));
        return list;
    }
}
